ユニットテスト
============

Yii のテストフレームワークは [PHPUnit](http://www.phpunit.de/) の上に構築されていますので、[PHPUnitのドキュメント](http://www.phpunit.de/manual/current/ja/index.html) を通読して、まずは、ユニットテストの書き方に関する基本的な理解を得ることをお奨めします。
以下に、Yii におけるユニットテストの書き方に関する基本的な原則を要約します。

 * ユニットテストは [CTestCase] または [CDbTestCase] を継承した `XyzTest` というクラスの形で書かれます。
ここで `Xyz` はテストされるクラスを表します。
例えば、`Post` クラスをテストするためには、対応するユニットテストの名前を `PostTest` とする、というのが規約です。
基本クラスの [CTestCase] は汎用のユニットテストのためのものであり、一方、 [CDbTestCase] は [アクティブレコード](/doc/guide/database.ar) モデルをテストするのに適しています。
二つのクラスは、共に、`PHPUnit_Framework_TestCase` を親クラスとして持っており、このクラスから継承した全てのメソッドを使用することが出来ます。
 
 * ユニットテストのクラスは `XyzTest.php` と名付けられた PHP ファイルに保存されます。
規約によって、ユニットテストのファイルはディレクトリ `protected/tests/unit` の下に保存します。

 * テストクラスは主として `testAbc` と名付けられた一連のテストメソッドを含みます。
ここで `Abc` は、多くの場合、テストされるクラスのメソッド名です。

 * テストメソッドは通常、一続きのアサーション文 (`assertTrue` や `assertEquals`) を含みます。
これらのアサーション文がターゲットクラスの振る舞いの妥当性を検証するチェックポイントとして働きます。

以下においては、主として、[アクティブレコード](/doc/guide/database.ar) モデルクラスのためのユニットテストを書く方法を説明します。
テストのクラスは [CDbTestCase] を継承したものにします。
というのは、[CDbTestCase] は前の章で紹介した、データベースフィクスチャのサポートを提供するからです。

[ブログデモ](http://www.yiiframework.com/demos/blog/) の中の `Comment` モデルクラスをテストしたいと仮定しましょう。
最初に `CommentTest` という名前のクラスを作成して、`protected/tests/unit/CommentTest.php` として保存します。

~~~
[php]
class CommentTest extends CDbTestCase
{
	public $fixtures=array(
		'posts'=>'Post',
		'comments'=>'Comment',
	);

	......
}
~~~

このクラスの中で、`fixtures` というメンバ変数を配列として定義し、このテストでどのフィクスチャが使用されるかを指定します。
配列は、フィクスチャの名前に対するモデルクラス名またはフィクスチャテーブル名 (例えば、`posts` というフィクスチャ名に対する `Post` というモデルクラス) という対応関係を表します。
フィクスチャテーブル名に対応付けるときは、テーブル名の前にコロンを付ける (例えば `:Post`) 必要があることに注意して下さい。
そして、モデルクラス名を使う場合は、モデルに対応するテーブルがフィクスチャテーブルであると見なされます。
前に述べたように、フィクスチャテーブルはテストメソッドが実行されるたびに、毎回、一定の既知の状態にリセットされます。

フィクスチャ名を使うと、テストメソッドの中で簡単にフィクスチャデータにアクセスすることが出来ます。
下記のコードがフィクスチャ名の典型的な使用例です。

~~~
[php]
// 'Comment' フィクスチャテーブルの全ての行を返す
$comments = $this->comments;
// `Post` フィクスチャテーブルの 'sample1' というエイリアスの行を返す
$post = $this->posts['sample1'];
// 'sample1' フィクスチャデータ行を表す AR インスタンスを返す
$post = $this->posts('sample1');
~~~

> Note|注意: テーブル名を使ってフィクスチャを宣言した場合 (例えば `'posts'=>':Post'`) は、上の三番目の用法はエラーになります。
なぜなら、テーブルがどんなモデルクラスに関連付けられているかについての情報が無いからです。

次に、`Comment` モデルクラスの `approve` メソッドをテストするための `testApprove` メソッドを書きます。
コードは非常に単純です。
最初に保留状態のコメントをインサートします。
次にこのコメントをデータベースから参照して、保留の状態にあることを確認します。最後に `approve` メソッドを呼んで、期待通りに状態が変化していることを確認します。

~~~
[php]
public function testApprove()
{
	// 保留状態のコメントを挿入する
	$comment=new Comment;
	$comment->setAttributes(array(
		'content'=>'comment 1',
		'status'=>Comment::STATUS_PENDING,
		'createTime'=>time(),
		'author'=>'me',
		'email'=>'me@example.com',
		'postId'=>$this->posts['sample1']['id'],
	),false);
	$this->assertTrue($comment->save(false));

	// コメントが保留状態であることを確認する
	$comment=Comment::model()->findByPk($comment->id);
	$this->assertTrue($comment instanceof Comment);
	$this->assertEquals(Comment::STATUS_PENDING,$comment->status);

	// approve() を呼んで、コメントが承認状態になったことを確認する
	$comment->approve();
	$this->assertEquals(Comment::STATUS_APPROVED,$comment->status);
	$comment=Comment::model()->findByPk($comment->id);
	$this->assertEquals(Comment::STATUS_APPROVED,$comment->status);
}
~~~

<div class="revision">$Id$</div>